home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
476-500
/
disk_478
/
mp
/
source
/
getopt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
7KB
|
246 lines
/****************************************************************************
* getopt(): Return the next user option on each iteration.
* This is a clone of the usual UNIX getopt() function.
* If you have never used a getopt() before, you'll have to
* read about it on any UNIX machine or other C system that
* documents it.
*
* Author: Daniel Barrett, barrett@cs.jhu.edu.
* Date: February 20, 1991.
* Version: 1.1.
*
* License: This code is placed in the Public Domain.
* Give it away to anybody for free!
* Use it for any purpose you like!
*
* If you use this code in a program, please give me credit
* for my work. Thanks!
*
* Why I wrote it:
*
* Because every other getopt() function I have ever seen
* had source code that was difficult to understand.
* I wrote this code to be very modular and readable.
* I hope you find it instructive and/or helpful.
*
* REVISION HISTORY:
* Version: 1.1
* Date: February 20, 1991.
* Comments: Bug fix in Pass(). Forgot to check that the
* current argument is non-empty and starts with
* a DASH.
*
* Got rid of the unnecessary "g_" at the beginning
* of each function name. Since they're static, we
* don't have to worry about duplication of names
* by the calling program.
*
* Version: 1.0
* Date: April 12, 1990.
* Comments: First released version.
*
****************************************************************************/
#ifndef __STDIO_H /* If we haven't already included stdio.h, do it. */
#include <stdio.h> /* Maybe someday I'll eliminate this. */
#endif
/************************************************************************
* Some constants.
************************************************************************/
#define DASH '-' /* This preceeds an option. */
#define ARG_COMING ':' /* In the option string, this indicates that
* that the option requires an argument. */
#define UNKNOWN_OPT '?' /* The char returned for unknown option. */
/************************************************************************
* Internal error codes.
************************************************************************/
#define ERROR_BAD_OPTION 1
#define ERROR_MISSING_ARGUMENT 2
/************************************************************************
* Mnemonic macros.
************************************************************************/
/************************************************************************
* ANSI function prototypes.
************************************************************************/
int getopt(int argc, char *argv[], char *optString);
static int NextOption(char *argv[], char *optString);
static int RealOption(char *argv[], char *str, int *skip, int *ind,
int opt);
static void HandleArgument(char *argv[], int *optind, int *skip);
static void Error(int err, int c);
static void Pass(char *argv[], int *optind, int *optsSkipped);
extern char *index();
/************************************************************************
* Global variables. You must declare these externs in your program
* if you want to see their values!
************************************************************************/
char *optarg = NULL; /* This will point to a required argument, if any. */
int optind = 1; /* The index of the next argument in argv. */
int opterr = 1; /* 1 == print internal error messages. 0 else. */
int optopt; /* The actual option letter that was found. */
int getopt(int argc, char *argv[], char *optString)
{
optarg = NULL;
if (optind < argc) /* More arguments to check. */
return(NextOption(argv, optString));
else /* We're done. */
return(EOF);
}
/* If the current argument does not begin with DASH, it is not an option.
* Return EOF.
* If we have ONLY a DASH, and nothing after it... return EOF as well.
* If we have a DASH followed immediately by another DASH, this is the
* special "--" option that means "no more options follow." Return EOF.
* Otherwise, we have an actual option or list of options. Process it. */
static int NextOption(char *argv[], char *optString)
{
static int optsSkipped = 0; /* In a single argv[i]. */
if ((argv[optind][0] == DASH)
&& ((optopt = argv[optind][1+optsSkipped]) != '\0'))
{
if (optopt == DASH)
{
optind++;
return(EOF);
}
else
return(RealOption(argv, optString, &optsSkipped,
&optind, optopt));
}
else
return(EOF);
}
/* At this point, we know that argv[optind] is an option or list of
* options. If this is a list of options, *optsSkipped tells us how
* many of those options have ALREADY been parsed on previous calls
* to getopt().
* If the option is not legal (not in optString), complain and return
* UNKNOWN_OPT.
* If the option requires no argument, just return the option letter.
* If the option requires an argument, call HandleArgument and return
* the option letter. */
static int RealOption(char *argv[], char *optString, int *optsSkipped,
int *optind, int optopt)
{
char *where;
(*optsSkipped)++;
if (where = index(optString, optopt))
{
if (*(where+1) == ARG_COMING)
HandleArgument(argv, optind, optsSkipped);
Pass(argv, optind, optsSkipped);
return(optopt);
}
else
{
Error(ERROR_BAD_OPTION, optopt);
Pass(argv, optind, optsSkipped);
return(UNKNOWN_OPT);
}
}
/* We have an option in argv[optind] that requires an argument. If there
* is no whitespace after the option letter itself, take the rest of
* argv[optind] to be the argument.
* If there IS whitespace after the option letter, take argv[optind+1] to
* be the argument.
* Otherwise, if there is NO argument, complain! */
static void HandleArgument(char *argv[], int *optind, int *optsSkipped)
{
if (argv[*optind][1+(*optsSkipped)])
optarg = argv[*optind] + 1 + (*optsSkipped);
else if (argv[(*optind)+1])
{
optarg = argv[(*optind)+1];
(*optind)++;
}
else
Error(ERROR_MISSING_ARGUMENT, optopt);
(*optsSkipped) = 0;
(*optind)++;
}
/* Print an appropriate error message. */
static void Error(int err, int c)
{
static char *optmsg = "Illegal option.\n";
static char *argmsg = "An argument is required, but missing.\n";
if (opterr)
{
if (err == ERROR_BAD_OPTION)
fprintf(stderr, "-%c: %s", c, optmsg);
else if (err == ERROR_MISSING_ARGUMENT)
fprintf(stderr, "-%c: %s", c, argmsg);
else /* Sanity check! */
fprintf(stderr, "-%c: an unknown error occurred\n",
c);
}
}
/* We have reached the end of argv[optind]... there are no more options
* in it to parse. Skip to the next item in argv. */
static void Pass(char *argv[], int *optind, int *optsSkipped)
{
if (argv[*optind]
&& (argv[*optind][0] == DASH)
&& (argv[*optind][1+(*optsSkipped)] == NULL))
{
(*optind)++;
(*optsSkipped) = 0;
}
}
/***************************************************************************
* A test program. Compile this file with -DTESTME as an option.
***************************************************************************/
#ifdef TESTME
main(int argc, char *argv[])
{
char c;
while ((c = getopt(argc, argv, "a:b:cde")) != EOF)
{
printf("OPTION %c", c);
if ((c == 'a') || (c == 'b'))
printf(", %s\n", optarg);
else
printf("\n");
printf("argc=%d, optind=%d\n", argc, optind);
}
exit(0);
}
#endif